Final project assignment -- data driven text adventure


“Data-driven” is when design your program so that it can be “driven” by a data file that is outside of the Python program, rather than hard coding all the variables within the program itself. This means that you want to load a text file containing structured data rather than defining variables using string literals within the py file itself.

You can find some example data structures and data files in the data_driven folder where you will submit your project (both the data file and the Python file).

Data-driven programs

For the final project you will need to expand your text adventure game that you built for the midterm project. You will make the code more compact and simpler, by moving some of it to data files. For the midterm project you probably used several nested if-else statements and had to repeat yourself a lot. One of the cardinal rules in software development is “Do not Repeat Yourself” (DRY). You can remove duplication (“DRY” your code) using some of the skills you have learned.

  1. Assign a variable to the data item you have repeated elsewhere.
  2. Create a function to reuse code multiple times.
  3. Remove hard-coded data from within your code and instead load it from data files.
  4. Use iteration, such as a while or for loop to do similar things repeatedly in your game.

You have probably already experimented with the first two, variables and functions. Now you are ready for those last two which you can use to create a data-driven text adventure program. Your final project for the course is to create a more fun and more elegant text adventure program, using the data-driven software design pattern.

Now that you know how to read and write data to files and how to use advanced iteration techniques you may be able to turn your game into a much more fun adventure, while at the same time reducing the number of lines of code in your program. The first step in building a data-driven program is creating a data structure to hold all your rooms for your text adventure. You can also use your data structure to store the possible commands for a game player to choose from in each room. You don’t have to show them to the player, but they should be available in the data structure for your program.

When thinking about data structures, the most useful container data types in Python are lists and dictionaries. For a list, you can only access the records in sequence or by knowing the integer position of an item in that list ahead of time. For a dictionary, you need to know the name of the key in order to find a particular value. A data structure will usually nest lists and dictionaries within each other to help you organize your data in a way that makes it easier for you to work with in your program.

Some common data structures to think about are:

  1. A list of lists — a table where you access the rows and columns based on their integer position, like in a spreadsheet or CSV file
  2. A list of dictionaries — each data record in your list can have different keys to make it easier to find something on that row.
  3. A dictionary of dictionaries — the dictionary keys can help you find both the row and the data within that row that you are looking for.
  4. A dictionary of lists — you can find a row of data based on its name and then iterate through a sequence of objects within the inner list.

1. list of lists

>>> X = [
...     [.707, .707, 0.0],
...     [.707, .707, 0.0],
...     [ 0.0,  0.0, 1.0],
... ]
>>> Y = [1, 0, 0]
>>> rotate45deg = [sum([x * y for x, y in zip(Xrow, Y)]) for Xrow in X]
>>> rotate45deg
[0.707, 0.707, 0.0]

Lists of lists, such as the one above, are used to store numerical data for for linear algebra and computer-generated graphics (CG) programs.

2. list of dictionaries

>>> peeps = [
...     {'name': "Kim", "age": 21},
...     {'name': 'Joe', 'phone': '867-5309'}
... ]
...
>>> [peep.get('age') for peep in peeps]
[21, None]
>>> [peep.get('name') for peep in peeps]
['Kim', 'Joe']

Lists of dictionariess, are used to store mixed data. You don’t even have to plan ahead of time for all the pieces of information that you might want to store. And each piece of information is optional.

3. dictionary of lists

>>> peeps = {
    'Lam':   ["Kim", 21,   None],
    'Smith': ['Jon', None, '867-5309'],
}
>>> peeps['Lam'][:2]
['Kim', 21]
>>> peeps['Smith'][:-1]
['Jon', None]

A dictionary of lists, are a good option if you always know the order of a set of information for each record or row in your dataset. You can always access each on with its key.

4. dictionary of dictionaries

>>> peeps = {
...     'Lam': {'name': "Kim", "age": 21},
...     'Smith': {'name': 'Jon', 'phone': '867-5309'},
... }
>>> peeps['Lam'].get('age')
21
>>> peeps['Smith']['age']
KeyError                                  Traceback (most recent call last)
>>> peeps['Smith'].get('age')

A dictionary of dictionariess, give you the ultimate in flexibility, you don’t need to control the order of the records in your data structure. You can always access each on with its key.

Text adventure data structure

A computer scientist would say that rooms in your text adventure game represent the “state” of your program. You can use the Listener Loop pattern (while True: or while command=input(question_for_user).strip(): loop) to listen for user commands forever. And you can use break or continue statements to control what happens in each room or at “Game Over.” A dictionary of dictionaries is probably a good data structure for your game.

Requirements

  • At least 10 rooms or states in your game.

  • At least 6 commands in each room.

  • Give your player a score at the end of the game. They should get 1 point for successfully visiting a room.

  • All the rooms must be reachable during a perfectly-played game.

  • All text displayed to the user must be stored in nested lists, dictionaries, or tuples.

  • All text displayed to the user is saved to a lastname.json file next to your program using the built-in json Python package.

  • Your program must be runnable from a terminal: I will run your code automatically on GitLab in the cisc-179-spring-2024/src/datadriven using the shell (terminal) command python yourlastname.py.

  • Bonus: all text displayed to the user is loaded from a json or csv file on disk (and submitted to GitLab along side your program).

  • Bonus: provide math or programming challenges that require a player to enter a correct number or json expression or python expression.